<!DOCTYPE html> <!-- -*- html -*- -->
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1">
  <title>Composition of Transformations</title>
  <link rel="shortcut icon" href="img/gatech.gif"/>

  
      <link rel="stylesheet" href="css/demo.css?vers=2759ff">
  

  <style>
      
html, body {
    margin:           0;
    height:           100%;
    background-color: white;
    overflow-x:       hidden;
}
.mathbox-wrapper {
    width:       33.333333%;
    padding-top: 33.333333%;
    position:    absolute;
    left:        0;
    top:         50%;
    transform:   translate(0, -50%);
    border:      1px solid black;
}
.mathbox-wrapper + .mathbox-wrapper {
    left: 33.333333%;
}
.mathbox-wrapper + .mathbox-wrapper + .mathbox-wrapper {
    left: 66.666666%;
}
.mathbox-wrapper > div {
    position: absolute;
    top:      0;
    left:     0;
    width:    100%;
    height:   100%;
}
.mathbox-label {
    position:  absolute;
    left:      50%;
    top:       10px;
    color:     black;
    opacity:   1.0;
    background-color: rgba(220, 220, 220, .5);
    border:    solid 1px rgba(50, 50, 50, .5);
    padding:   5px;
    transform: translate(-50%, 0);
}
.overlay-text {
    z-index: 1;
}

  </style>

</head>
<body>
    

<div class="overlay-text">
  <p><span id="matrix1-here"></span></p>
  <p><span id="matrix2-here"></span></p>
  <p><span id="matrix3-here"></span></p>
</div>

<div class="mathbox-wrapper">
    <div id="mathbox1">
        
<div class="mathbox-label">Input of U</div>

    </div>
</div>
<div class="mathbox-wrapper">
    <div id="mathbox2">
        
<div class="mathbox-label">Output of U / Input of T</div>

    </div>
</div>
<div class="mathbox-wrapper">
    <div id="mathbox3">
        
<div class="mathbox-label">Output of T / of T &#x25CB; U</div>

    </div>
</div>


    
        <script src="js/demo.js?vers=77646a"></script>
    

    <script type="text/javascript">
        "use strict";
        DomReady.ready(function() {

        var color1, color2, color3, computeOut, dark1, dark2, dark3, demos, dim1, dim2, dim3, gui, matrix1, matrix1Elt, matrix2, matrix2Elt, matrix3, matrix3Elt, params, setupDemo, tMatrix1, tMatrix2, tmpVec, transpose, updateCaption, vector1, vector2, vector3;

vector1 = urlParams.get('x', 'float[]', [-1, 2, 3]);

vector2 = [0, 0, 0];

vector3 = [0, 0, 0];

color1 = new Color("green");

color2 = new Color("violet");

color3 = new Color("red");

matrix1 = urlParams.get('mat1', 'matrix', [[1, 0, 0], [0, 1, 0], [0, 0, 1]]);

matrix2 = urlParams.get('mat2', 'matrix', [[1, 0, 0], [0, 1, 0], [0, 0, 1]]);

dim1 = matrix1[0].length;

dim2 = matrix2[0].length;

dim3 = matrix2.length;

if (dim1 === 2) {
  vector1[2] = 0;
}

transpose = function(mat) {
  var i, j, k, l, ref, ref1, tmp;
  tmp = [];
  for (i = k = 0; k < 3; i = ++k) {
    tmp[i] = [];
    for (j = l = 0; l < 3; j = ++l) {
      tmp[i][j] = (ref = (ref1 = mat[j]) != null ? ref1[i] : void 0) != null ? ref : 0;
    }
  }
  return tmp;
};

matrix1 = transpose(matrix1);

matrix2 = transpose(matrix2);

matrix3 = [[matrix2[0][0] * matrix1[0][0] + matrix2[1][0] * matrix1[0][1] + matrix2[2][0] * matrix1[0][2], matrix2[0][1] * matrix1[0][0] + matrix2[1][1] * matrix1[0][1] + matrix2[2][1] * matrix1[0][2], matrix2[0][2] * matrix1[0][0] + matrix2[1][2] * matrix1[0][1] + matrix2[2][2] * matrix1[0][2]], [matrix2[0][0] * matrix1[1][0] + matrix2[1][0] * matrix1[1][1] + matrix2[2][0] * matrix1[1][2], matrix2[0][1] * matrix1[1][0] + matrix2[1][1] * matrix1[1][1] + matrix2[2][1] * matrix1[1][2], matrix2[0][2] * matrix1[1][0] + matrix2[1][2] * matrix1[1][1] + matrix2[2][2] * matrix1[1][2]], [matrix2[0][0] * matrix1[2][0] + matrix2[1][0] * matrix1[2][1] + matrix2[2][0] * matrix1[2][2], matrix2[0][1] * matrix1[2][0] + matrix2[1][1] * matrix1[2][1] + matrix2[2][1] * matrix1[2][2], matrix2[0][2] * matrix1[2][0] + matrix2[1][2] * matrix1[2][1] + matrix2[2][2] * matrix1[2][2]]];

tMatrix1 = new THREE.Matrix3();

tMatrix1.set(matrix1[0][0], matrix1[1][0], matrix1[2][0], matrix1[0][1], matrix1[1][1], matrix1[2][1], matrix1[0][2], matrix1[1][2], matrix1[2][2]);

tMatrix2 = new THREE.Matrix3();

tMatrix2.set(matrix2[0][0], matrix2[1][0], matrix2[2][0], matrix2[0][1], matrix2[1][1], matrix2[2][1], matrix2[0][2], matrix2[1][2], matrix2[2][2]);

params = {
  Axes: urlParams.get('axes', 'bool', true)
};

params["range U"] = urlParams.get('rangeU', 'bool', true);

params["range T"] = urlParams.get('rangeT', 'bool', true);

params["range TU"] = urlParams.get('rangeTU', 'bool', true);

gui = new dat.GUI();

gui.closed = urlParams.closed != null;

gui.add(params, 'Axes').onFinishChange(function(val) {
  var i, k, results;
  results = [];
  for (i = k = 0; k < 3; i = ++k) {
    results.push(demos[i].mathbox.select(".view" + (i + 1) + "-axes").set('visible', val));
  }
  return results;
});

tmpVec = new THREE.Vector3();

computeOut = function() {
  tmpVec.set.apply(tmpVec, vector1).applyMatrix3(tMatrix1);
  vector2[0] = tmpVec.x;
  vector2[1] = tmpVec.y;
  vector2[2] = tmpVec.z;
  tmpVec.applyMatrix3(tMatrix2);
  vector3[0] = tmpVec.x;
  vector3[1] = tmpVec.y;
  vector3[2] = tmpVec.z;
  return updateCaption();
};

if (urlParams.range != null) {
  urlParams.range1 = urlParams.range2 = urlParams.range3 = urlParams.range;
}

setupDemo = function(opts) {
  return new (opts.dim === 3 ? Demo : Demo2D)({
    mathbox: {
      element: document.getElementById("mathbox" + opts.index)
    },
    scaleUI: false
  }, function() {
    var labeled, r, range;
    this.index = opts.index, this.vector = opts.vector, this.dim = opts.dim, this.color = opts.color, this.label = opts.label;
    window["mathbox" + this.index] = this.mathbox;
    range = urlParams.get("range" + this.index, 'float', 10.0);
    r = range;
    this.viewObj = this.view({
      name: "view" + this.index,
      viewRange: [[-r, r], [-r, r], [-r, r]].slice(0, this.dim),
      axisLabels: false
    });
    this.mathbox.select(".view" + this.index + "-axes").set('visible', params.Axes);
    labeled = this.labeledVectors(this.viewObj, {
      name: "labeled" + this.index,
      vectors: [this.vector],
      colors: [this.color],
      labels: [this.label],
      live: true,
      zeroPoints: true,
      zeroThreshold: 0.1,
      vectorOpts: {
        zIndex: 2
      },
      labelOpts: {
        zIndex: 3
      },
      zeroOpts: {
        zIndex: 3
      }
    });
    return this.clipCubeObj = this.clipCube(this.viewObj, {
      draw: this.dim === 3,
      hilite: this.dim === 3,
      material: new THREE.MeshBasicMaterial({
        color: new THREE.Color(0, 0, 0),
        opacity: 0.5,
        transparent: true,
        visible: false,
        depthWrite: false,
        depthTest: true
      })
    });
  });
};

window.demo1 = setupDemo({
  index: 1,
  vector: vector1,
  dim: dim1,
  color: color1,
  label: 'x'
});

window.demo2 = setupDemo({
  index: 2,
  vector: vector2,
  dim: dim2,
  color: color2,
  label: 'U(x)'
});

window.demo3 = setupDemo({
  index: 3,
  vector: vector3,
  dim: dim3,
  color: color3,
  label: 'T(U(x))'
});

demos = [demo1, demo2, demo3];

groupControls(demo1, demo2, demo3);

demo1.draggable(demo1.viewObj, {
  points: [vector1],
  postDrag: computeOut
});

dark1 = color1.darken(.1);

demo2.rangeU = demo2.subspace({
  name: 'rangeU',
  vectors: matrix1,
  live: false,
  color: dark1,
  mesh: demo2.clipCubeObj.mesh
});

if (demo2.rangeU.dim === 3) {
  demo2.clipCubeObj.installMesh();
  demo2.clipCubeObj.mesh.material.color.copy(dark1);
}

demo2.rangeU.draw(demo2.clipCubeObj.clipped);

demo2.rangeU.setVisibility(params['range U']);

dark2 = color2.darken(.1);

demo3.rangeT = demo3.subspace({
  name: 'rangeT',
  vectors: matrix2,
  live: false,
  color: dark2,
  mesh: demo3.clipCubeObj.mesh
});

demo3.rangeT.draw(demo3.clipCubeObj.clipped);

demo3.rangeT.setVisibility(params['range T']);

dark3 = color1.darken(.1);

demo3.rangeTU = demo3.subspace({
  name: 'rangeTU',
  vectors: matrix3,
  live: false,
  color: dark3,
  mesh: demo3.clipCubeObj.mesh
});

demo3.rangeTU.draw(demo3.clipCubeObj.clipped);

demo3.rangeTU.setVisibility(params['range TU']);

if (demo3.rangeT.dim === 3 || demo3.rangeTU.dim === 3) {
  demo3.clipCubeObj.installMesh();
}

gui.add(params, 'range U').onFinishChange(demo2.rangeU.setVisibility);

gui.add(params, 'range T').onFinishChange(function(val) {
  if (val && demo3.rangeT.dim === 3) {
    demo3.clipCubeObj.mesh.material.color.copy(dark2);
  }
  return demo3.rangeT.setVisibility(val);
});

gui.add(params, 'range TU').onFinishChange(function(val) {
  if (val && demo3.rangeTU.dim === 3) {
    demo3.clipCubeObj.mesh.material.color.copy(dark3);
  }
  return demo3.rangeTU.setVisibility(val);
});

matrix1Elt = document.getElementById('matrix1-here');

matrix2Elt = document.getElementById('matrix2-here');

matrix3Elt = document.getElementById('matrix3-here');

updateCaption = function() {
  var str;
  str = "U(\\color{" + (color1.str()) + "}{x}) = ";
  str += demo1.texMatrix(matrix1, {
    cols: dim1,
    rows: dim2
  });
  str += demo1.texVector(vector1, {
    color: color1.str()
  });
  str += "=";
  str += demo2.texVector(vector2, {
    color: color2.str()
  });
  katex.render(str, matrix1Elt);
  str = "T(\\color{" + (color2.str()) + "}{U(x)}) = ";
  str += demo2.texMatrix(matrix2, {
    cols: dim2,
    rows: dim3
  });
  str += demo2.texVector(vector2, {
    color: color2.str()
  });
  str += "=";
  str += demo3.texVector(vector3, {
    color: color3.str()
  });
  katex.render(str, matrix2Elt);
  str = "T\\circ U(\\color{" + (color1.str()) + "}{x}) = ";
  str += demo1.texMatrix(matrix3, {
    cols: dim1,
    rows: dim3
  });
  str += demo1.texVector(vector1, {
    color: color1.str()
  });
  str += "=";
  str += demo3.texVector(vector3, {
    color: color3.str()
  });
  return katex.render(str, matrix3Elt);
};

computeOut();


        });
    </script>
</body>
</html>

